home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / human interface toolbox / datething / datedialog.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  23.4 KB  |  633 lines

  1. /*
  2.     File:        DateDialog.c
  3.  
  4.     Contains:    an example of how to create a date-adjuster type thing    
  5.                 as used in the General control panel
  6.  
  7.     Written by: C.K. Haun    
  8.  
  9.     Copyright:    Copyright © 1999 by Apple Computer, Inc., All Rights Reserved.
  10.  
  11.                 You may incorporate this Apple sample source code into your program(s) without
  12.                 restriction. This Apple sample source code has been provided "AS IS" and the
  13.                 responsibility for its operation is yours. You are not permitted to redistribute
  14.                 this Apple sample source code as "Apple sample source code" after having made
  15.                 changes. If you're going to re-distribute the source, we require that you make
  16.                 it clear in the source that the code was descended from Apple sample source
  17.                 code, but that you've made changes.
  18.  
  19.     Change History (most recent first):
  20.                 7/19/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  21.                 
  22. */
  23. #include "DateThing.h"
  24. #include <TextUtils.h>
  25. /* protos for this file */
  26.  
  27. static ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem);
  28. static void WritePicturedNum(long theNum, short width);
  29. static pascal void BorderDefault(DialogPtr dwind, short dinum);
  30. static void DrawIndString(short strList, short index);
  31. static pascal void DateBox(WindowPtr rDial, short dinum);
  32. static void AdjustDate(short incOr, DialogPtr rDial, short newVal);
  33. static pascal Boolean DateThingerFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit);
  34.  
  35. /* exported */
  36. void DateSetterDialog(void);
  37.  
  38. /* I like to keep the seconds and the 'real' representation of the date all the */
  39. /* time instead of doing a lot of conversions */
  40. /* so this struct */
  41.  
  42. typedef struct DateStruct {
  43.     Boolean inUse;
  44.     unsigned long startDateraw;
  45.     unsigned long endDateraw;
  46.     DateTimeRec startDate;
  47.     DateTimeRec endDate;
  48. } DateStruct, *DatePtr, **DateHdl;
  49.  
  50. typedef struct dateBoxStruct {
  51.     DateStruct dialogDate;  /* contains the current start and end dates */
  52.     Rect charBox[6];        /* rectangles containing the numbers */
  53.     Rect arrowHits[2];      /* test if the user is in my arrows */
  54.     Boolean editHot;        /* if this is active. aways true in this example */
  55.                             /* this is in here if you also have an edit line in the dialog */
  56.                             /* and you need to direct keys to that edit line instead of the */
  57.                             /* date thing sometimes */
  58.     short whichHitting;     /* what month/day etc. are we currently in? */
  59.     Rect thing;             /* where the thing goes */
  60.     long lastLetterTick;    /* when was the last time they typed something */
  61.     short lastWhichHit;     /* in what area? */
  62. } dateBoxStruct;
  63. static dateBoxStruct dialogDateStruct;
  64.  
  65. enum  {
  66.     kManDateItem = 3, kBorderBox
  67. };
  68.  
  69. enum  {
  70.     kStartMonth = 0, kStartDay, kStartYear, kEndMonth, kEndDay, kEndYear
  71. };
  72. #pragma segment Main
  73.  
  74. /* Gets the ControlHandle for the item you want in the dialog box thebox. */
  75. /* Handy for setting checkboxes and radio buttons */
  76.  
  77. static ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem)
  78. {
  79.     short itemtype;
  80.     Rect itemrect;
  81.     Handle thandle;
  82.     
  83.     GetDialogItem(thebox, theGetItem, &itemtype, &thandle, &itemrect);
  84.     return((ControlHandle)thandle);
  85. }
  86.  
  87. /* end SnatchHandle */
  88.  
  89. /* puts leading spaces as needed */
  90. /* replaces <# # # # #> in FORTH */
  91.  
  92. static void WritePicturedNum(long theNum, short width)
  93. {
  94.     Str32 theNumber;
  95.     short spAdd = 0;
  96.     NumToString(theNum,theNumber);
  97.     if (width <= 31) {
  98.         if (theNumber[0] != width) {
  99.             /* padd until */
  100.             /* shift over some */
  101.             spAdd = width - theNumber[0];
  102.             BlockMove((Ptr)&theNumber[1], (Ptr)&theNumber[spAdd + 1], theNumber[0]);
  103.             
  104.             while (spAdd) {
  105.                 theNumber[spAdd] = '0';
  106.                 spAdd--;
  107.             }
  108.             theNumber[0] = width;
  109.         }
  110.     }
  111.     DrawString(theNumber);
  112.     
  113. } /* end WritePicturedNum */
  114.  
  115. /* util */
  116.  
  117. /* BorderDefault draws a heavy border around the default button (in this case the OK button ) */
  118. /* Not necessary if SetDefaultItem is used in System 7 (see DialogBits 2.0.1) */
  119.  
  120. static pascal void BorderDefault(DialogPtr dwind, short dinum)
  121. {
  122. #pragma unused (dinum)
  123.     short itemtype;
  124.     Handle itemhandle;
  125.     Rect borderRect;
  126.     GetDialogItem(dwind, ok, &itemtype, &itemhandle, &borderRect);
  127.     /* ok is defined as 1 in the interfaces. If you'd like another item outlined, */
  128.     /* change this number, of course. */
  129.     InsetRect(&borderRect, -4, -4);
  130.     PenSize(3, 3);
  131.     FrameRoundRect(&borderRect, 16, 16);
  132.     PenSize(1, 1);
  133. }
  134.  
  135. /* end BorderDefault */
  136.  
  137. /* Replaces constantly calling Get/Draw string */
  138.  
  139. static void DrawIndString(short strList, short index)
  140. {
  141.     Str255 theString;
  142.     GetIndString(theString, strList, index);
  143.     DrawString(theString);
  144.     
  145. }
  146.  
  147. /* end DrawIndString */
  148.  
  149. /* DateBox actually draws the two dates in the userItem rect set up for them */
  150.  
  151. static pascal void DateBox(WindowPtr rDial, short dinum)
  152. {
  153. #pragma unused (dinum )
  154.     short kindI, oldFont;
  155.     Handle HandL;
  156.     Rect itemRect;
  157.     Rect thiRect;
  158.     short  tWide, tHi;
  159.     short tenFnum, oldSize;
  160.     PicHandle theHittedThing;
  161.     short index = 0;
  162.     
  163.     GetDialogItem(rDial, kManDateItem, &kindI, &HandL, &itemRect);
  164.     EraseRect(&itemRect);
  165.     
  166.     /* I am using Monaco here because it's a monospaced font, and I want */
  167.     /* the date things not to shift all the time by characters changing width */
  168.     
  169.     GetFNum("\pMonaco", &tenFnum);
  170.     
  171.     /* save the old font and size */
  172.     oldFont = rDial->txFont;
  173.     oldSize = rDial->txSize;
  174.     
  175.     /* set the new font and size */
  176.     TextFont(tenFnum);
  177.     TextSize(12);
  178.     
  179.     /* plot our numbers */
  180.     MoveTo(itemRect.left, itemRect.bottom - 7);
  181.     
  182.     /* I'm doing getpens so I can make the correct inversion and hit testing rectangles */
  183.     
  184.     GetPen((Point *)&(dialogDateStruct.charBox[index].top));
  185.     WritePicturedNum(dialogDateStruct.dialogDate.startDate.month, 2);
  186.     GetPen((Point *)&(dialogDateStruct.charBox[index].bottom));
  187.     index++;
  188.     
  189.     DrawChar('/');
  190.     GetPen((Point *)&(dialogDateStruct.charBox[index].top));
  191.     WritePicturedNum(dialogDateStruct.dialogDate.startDate.day, 2);
  192.     GetPen((Point *)&(dialogDateStruct.charBox[index].bottom));
  193.     index++;
  194.     
  195.     DrawChar('/');
  196.     GetPen((Point *)&(dialogDateStruct.charBox[index].top));
  197.     WritePicturedNum(dialogDateStruct.dialogDate.startDate.year, 4);
  198.     GetPen((Point *)&(dialogDateStruct.charBox[index].bottom));
  199.     index++;
  200.     
  201.     DrawIndString(kGeneralStrings, kToWord);
  202.     GetPen((Point *)&(dialogDateStruct.charBox[index].top));
  203.     WritePicturedNum(dialogDateStruct.dialogDate.endDate.month, 2);
  204.     GetPen((Point *)&(dialogDateStruct.charBox[index].bottom));
  205.     index++;
  206.     
  207.     DrawChar('/');
  208.     GetPen((Point *)&(dialogDateStruct.charBox[index].top));
  209.     WritePicturedNum(dialogDateStruct.dialogDate.endDate.day, 2);
  210.     GetPen((Point *)&(dialogDateStruct.charBox[index].bottom));
  211.     index++;
  212.     
  213.     DrawChar('/');
  214.     GetPen((Point *)&(dialogDateStruct.charBox[index].top));
  215.     WritePicturedNum(dialogDateStruct.dialogDate.endDate.year, 4);
  216.     GetPen((Point *)&(dialogDateStruct.charBox[index].bottom));
  217.     
  218.     /* draw the arrow picture thing */
  219.     /* assumes itemRect && index ain't changed, so don't mess 'em up before here */
  220.     /* get my picture of the up/down arrows */
  221.     theHittedThing = GetPicture(129);
  222.     thiRect = (*theHittedThing)->picFrame;
  223.     
  224.     /* get the basic dimensions of the picture */
  225.     tWide = thiRect.right - thiRect.left;
  226.     tHi = thiRect.bottom - thiRect.top;
  227.     
  228.     /* move it to after the last year */
  229.     thiRect.left = dialogDateStruct.charBox[index].right + 5;
  230.     thiRect.right = thiRect.left + tWide;
  231.     thiRect.bottom = itemRect.bottom - 7;
  232.     thiRect.top = thiRect.bottom - tHi;
  233.     
  234.     DrawPicture(theHittedThing, &thiRect);
  235.     /* reset arrowHits */
  236.     dialogDateStruct.arrowHits[0] = thiRect;
  237.     dialogDateStruct.arrowHits[1] = thiRect;
  238.     
  239.     dialogDateStruct.arrowHits[0].bottom = dialogDateStruct.arrowHits[0].top + ((dialogDateStruct.arrowHits[0].bottom -
  240.                                                                                  dialogDateStruct.arrowHits[0].top) / 2);
  241.     dialogDateStruct.arrowHits[1].top = dialogDateStruct.arrowHits[0].bottom + 1;       /* slight slop */
  242.     ReleaseResource((Handle)theHittedThing);
  243.     
  244.     for (index = 0; index < 6; index++) {
  245.         FontInfo theFInfo;
  246.         GetFontInfo(&theFInfo);
  247.         /* set the top and bottom of the character rectangles */
  248.         dialogDateStruct.charBox[index].bottom += 4;
  249.         dialogDateStruct.charBox[index].top = dialogDateStruct.charBox[index].bottom - theFInfo.ascent - theFInfo.descent -
  250.             theFInfo.leading;
  251.         
  252.         /* invert the current one so the user knows it's active */
  253.         if (dialogDateStruct.editHot && dialogDateStruct.whichHitting == index)
  254.             InvertRect(&dialogDateStruct.charBox[index]);
  255.     }
  256.     /* reset to the old font and size */
  257.     TextFont(oldFont);
  258.     TextSize(oldSize);
  259.     
  260. }
  261.  
  262. /* end DateBox */
  263.  
  264. /* adjusts the current date if a key has been hit, mouse clicked, whatever */
  265. /* adding some extra stuff for using this from keystrokes */
  266. static void AdjustDate(short incOr, DialogPtr rDial, short newVal)
  267. {
  268.     short *theThing;
  269.     DateStruct originalDate;
  270.     RgnHandle oldClip, currentClip;
  271.     short amt;
  272.     
  273.     /* save the initial months for rollover checking */
  274.     originalDate = dialogDateStruct.dialogDate;
  275.     
  276.     /* switch off which unit we're currently tracking */
  277.     switch (dialogDateStruct.whichHitting) {
  278.         case kStartMonth:
  279.             theThing = (short *)&dialogDateStruct.dialogDate.startDate.month;
  280.             break;
  281.         case kStartDay:
  282.             theThing = (short *)&dialogDateStruct.dialogDate.startDate.day;
  283.             break;
  284.         case kStartYear:
  285.             theThing = (short *)&dialogDateStruct.dialogDate.startDate.year;
  286.             
  287.             break;
  288.         case kEndMonth:
  289.             theThing = (short *)&dialogDateStruct.dialogDate.endDate.month;
  290.             
  291.             break;
  292.         case kEndDay:
  293.             theThing = (short *)&dialogDateStruct.dialogDate.endDate.day;
  294.             break;
  295.         case kEndYear:
  296.             theThing = (short *)&dialogDateStruct.dialogDate.endDate.year;
  297.             break;
  298.     }
  299.     /* dammit! oh, nevermind, I figured it out */
  300.     if (newVal < 0) {
  301.         /* set the increment to plus one or minus 1 */
  302.         amt = (incOr ? -1 : 1);
  303.         /* and change the value */
  304.         *theThing += amt;
  305.     } else {
  306.         if (dialogDateStruct.whichHitting == kStartYear || dialogDateStruct.whichHitting == kEndYear) {
  307.             /* I forget why this is here, but I must have had a good reason */
  308.         } else {
  309.             short oldThing;
  310.             /* ok, dammit, if it's a two-stroker then do 2 stroke things */
  311.             /* Which means the user might have hit two numbers quickly (like 1 0 to indicate 10) */
  312.             /* so we have to handle that, instead of treating every numeric stroke as a */
  313.             /* number in the 1's column */
  314.             if (TickCount() < dialogDateStruct.lastLetterTick) {
  315.                 oldThing = *theThing;
  316.                 *theThing *= 10;
  317.                 /* check range for months, forget days */
  318.                 if (dialogDateStruct.whichHitting == kStartMonth || dialogDateStruct.whichHitting == kEndMonth) {
  319.                     
  320.                     if ((*theThing + newVal) < 13) {
  321.                         /* if over 13, then reset it */
  322.                         newVal = *theThing + newVal;
  323.                     }
  324.                 } else {
  325.                     /* Should we do days? OK, but forget february */
  326.                     if ((*theThing + newVal) < 32) {
  327.                         newVal = *theThing + newVal;
  328.                     }
  329.                 }
  330.             }
  331.             *theThing = newVal;
  332.             
  333.             /* set up for the second in a two-key number entry. They have to hit the second */
  334.             /* key within 60 ticks for it to count with the first one */
  335.             dialogDateStruct.lastLetterTick = TickCount() + 60;
  336.         }
  337.     }
  338.     /* let the utils figure out if they wrapped or not */
  339.     
  340.     DateToSeconds(&dialogDateStruct.dialogDate.startDate, &dialogDateStruct.dialogDate.startDateraw);
  341.     DateToSeconds(&dialogDateStruct.dialogDate.endDate, &dialogDateStruct.dialogDate.endDateraw);
  342.     /* HAHAHA and now the other way */
  343.     SecondsToDate(dialogDateStruct.dialogDate.startDateraw, &dialogDateStruct.dialogDate.startDate);
  344.     SecondsToDate(dialogDateStruct.dialogDate.endDateraw, &dialogDateStruct.dialogDate.endDate);
  345.     
  346.     /* check for rollovers */
  347.     /* I _think_ the only rollover occurs with days, so check that only */
  348.     /* Nope, have to check for months rolling over years and days */
  349.     /* Stop being inefficient, and just keep building a bigger region, OK? */
  350.     
  351.     /* Save the old clipping region, and set up a new one that */
  352.     /* will include just the rectangles that change */
  353.     oldClip = NewRgn();
  354.     GetClip(oldClip);
  355.     currentClip = NewRgn();
  356.     OpenRgn();
  357.     
  358.     /* clip to the currently hitting character */
  359.     FrameRect(&dialogDateStruct.charBox[dialogDateStruct.whichHitting]);
  360.     
  361.     /* now go through any side-effects and clip to them also */
  362.     /* Side effects like days rolling past 31 and the month changing */
  363.     
  364.     switch (dialogDateStruct.whichHitting) {
  365.         case kStartMonth:
  366.             /* Did the year or day change because of this month change? */
  367.             if (originalDate.startDate.year != dialogDateStruct.dialogDate.startDate.year)
  368.                 FrameRect(&dialogDateStruct.charBox[kStartYear]);
  369.             if (originalDate.startDate.day != dialogDateStruct.dialogDate.startDate.day)
  370.                 FrameRect(&dialogDateStruct.charBox[kStartDay]);
  371.             
  372.             break;
  373.         case kStartDay:
  374.             /* Did the month change because of this day change? */
  375.             
  376.             if (originalDate.startDate.month != dialogDateStruct.dialogDate.startDate.month)
  377.                 FrameRect(&dialogDateStruct.charBox[kStartMonth]);
  378.             
  379.             break;
  380.             
  381.         case kEndMonth:
  382.             /* Did the year or day change because of this month change? */
  383.             if (originalDate.endDate.year != dialogDateStruct.dialogDate.endDate.year)
  384.                 FrameRect(&dialogDateStruct.charBox[kEndYear]);
  385.             if (originalDate.endDate.day != dialogDateStruct.dialogDate.endDate.day)
  386.                 FrameRect(&dialogDateStruct.charBox[kEndDay]);
  387.             
  388.             
  389.             break;
  390.         case kEndDay:
  391.             /* Did the month change because of this day change? */
  392.             
  393.             if (originalDate.endDate.month != dialogDateStruct.dialogDate.endDate.month)
  394.                 FrameRect(&dialogDateStruct.charBox[kEndMonth]);
  395.             
  396.             break;
  397.             
  398.     }
  399.     CloseRgn(currentClip);
  400.     
  401.     /* Clip to these boxes */
  402.     SetClip(currentClip);
  403.     
  404.     /* redraw the date */
  405.     DateBox(rDial, kManDateItem);
  406.     
  407.     /* restore original clip */
  408.     SetClip(oldClip);
  409.     
  410.     /* dispose of our temp regions */
  411.     DisposeRgn(currentClip);
  412.     DisposeRgn(oldClip);
  413. }
  414.  
  415. /* end AdjustDate */
  416.  
  417. /* DateThingerFilter */
  418. /* Filters events for the date dialog */
  419. enum  {
  420.         kGoingUp = 1, kGoingDown
  421.     };
  422. pascal Boolean DateThingerFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  423. {
  424. #pragma unused (itemHit )
  425.     
  426.     Boolean retVal = false;
  427.     WindowPtr theOld;
  428.     unsigned long qq;
  429.     short kindI;
  430.     short upOrDown = 0;
  431.     Handle HandL;
  432.     Rect itemRect;
  433.     unsigned long tempLong;
  434.     Point thePoint;
  435.     GetPort(&theOld);
  436.     SetPort(theDialog);
  437.     if (theEvent->what == mouseDown) {
  438.         
  439.         /* if the event is a mouse down, it could be in a number or an arrow */
  440.         GetMouse(&thePoint);
  441.         
  442.         /* check arrow box first */
  443.         if (PtInRect(thePoint, &dialogDateStruct.arrowHits[0])) {
  444.             upOrDown = kGoingUp;
  445.         } else {
  446.             if (PtInRect(thePoint, &dialogDateStruct.arrowHits[1])) {
  447.                 upOrDown = kGoingDown;
  448.             }
  449.         }
  450.         /* if upOrDown was set, then it was in a arrow */
  451.         if (upOrDown) {
  452.             /* for the arrow picture */
  453.             
  454.             InvertRect(&dialogDateStruct.arrowHits[upOrDown - 1]);
  455.             /* stay with it and blink */
  456.             Delay(8,&tempLong);
  457.             
  458.             while (StillDown()) {
  459.                 /* if they are holding down in the arrow thing, then wait 8 ticks */
  460.                 /* for them to come up, if they don't adjust again */
  461.                 /* making this a subroutine to keep the clutter out of this filter */
  462.                 AdjustDate(upOrDown - 1, theDialog, -1);
  463.                 Delay(8, &tempLong);
  464.             }
  465.             InvertRect(&dialogDateStruct.arrowHits[upOrDown - 1]);
  466.             
  467.         } else {
  468.             /* they didn't click in an arrow, maybe they clicked in a number */
  469.             for (qq = 0; qq < 6; qq++) {
  470.                 /* see if in the hot numbers */
  471.                 if (PtInRect(thePoint, &dialogDateStruct.charBox[qq])) {
  472.                     dialogDateStruct.editHot = true;
  473.                     dialogDateStruct.whichHitting = qq;
  474.                     
  475.                     /* invalidate the whole date so the new number */
  476.                     /* gets inverted and the old one loses it's invert */
  477.                     GetDialogItem(theDialog, kManDateItem, &kindI, &HandL, &itemRect);
  478.                     InvalRect(&itemRect);
  479.                     retVal = true;
  480.                     break;
  481.                 }
  482.             }
  483.         }
  484.     } else {
  485.         
  486.         /* see if they entered a number or arrow or tab */
  487.         if (theEvent->what == keyDown) {
  488.             char theKey = theEvent->message &charCodeMask;
  489.             
  490.             if (theKey == kTabKey && dialogDateStruct.editHot) {
  491.                 /* OK dang it, I'll add shift-reverse tabbing. grumble grumble */
  492.                 
  493.                 /* blow away the lastKey ticks */
  494.                 
  495.                 dialogDateStruct.lastLetterTick = 0;
  496.                 InvalRect(&dialogDateStruct.charBox[dialogDateStruct.whichHitting]);
  497.                 
  498.                 if (theEvent->modifiers & shiftKey)
  499.                     dialogDateStruct.whichHitting--;
  500.                 else
  501.                     dialogDateStruct.whichHitting++;
  502.                 
  503.                 /* wrap around on tabbing */
  504.                 if (dialogDateStruct.whichHitting >= 6)
  505.                     dialogDateStruct.whichHitting = kStartMonth;
  506.                 
  507.                 if (dialogDateStruct.whichHitting < 0)
  508.                     dialogDateStruct.whichHitting = kEndYear;
  509.                 
  510.                 InvalRect(&dialogDateStruct.charBox[dialogDateStruct.whichHitting]);
  511.                 
  512.             } else {
  513.                 /* see if it's a number, or heck, an arrow */
  514.                 if ((theKey > 0x2f && theKey < 0x3a) && dialogDateStruct.editHot) {
  515.                     /* hmmmm. Now what do we do? */
  516.                     /* I'm just going to stuff the number in the last digit of the year, or */
  517.                     /* the month/day */
  518.                     /* forget it, let the real thing figure it out */
  519.                     AdjustDate(nil, theDialog, theKey - 0x30);
  520.                     
  521.                 } else {
  522.                     /* do some other standard key stuff */
  523.                     switch (theKey) {
  524.                         short tempItem;
  525.                         Handle tempHandle;
  526.                         Rect tempRect;
  527.                         
  528.                         case kLeftArrowKey:
  529.                         case kDownArrowKey:
  530.                             upOrDown = kGoingDown;
  531.                             break;
  532.                         case kRightArrowKey:
  533.                         case kUpArrowKey:
  534.                             upOrDown = kGoingUp;
  535.                             break;
  536.                         case kEscKey:
  537.                             *itemHit = 2;
  538.                             GetDialogItem(theDialog, 1, &tempItem, &tempHandle, &tempRect);
  539.                             
  540.                             if (tempItem == ctrlItem) {
  541.                                 /* much more likely that this may not be a button */
  542.                                 
  543.                                 HiliteControl(SnatchHandle(theDialog, cancel), kControlButtonPart);
  544.                                 Delay(8, &tempLong);        /* wait about 8 ticks so they can see it */
  545.                                 HiliteControl(SnatchHandle(theDialog, cancel), false);
  546.                                 retVal = true;
  547.                             }
  548.                             break;
  549.                         case kReturnKey:
  550.                         case kEnterKey:                     /* enter key */
  551.                             /* This filters for Return or Enter as item 1, and Esc as item 2 */
  552.                             *itemHit = 1;                   /* change whatever the current item is to the OK item */
  553.                             /* now we need to invert the button */
  554.                             GetDialogItem(theDialog, 1, &tempItem, &tempHandle, &tempRect);
  555.                             if (tempItem == ctrlItem) {
  556.                                 /* double check for the unlikely event that this is _not_ a button */
  557.                                 HiliteControl(SnatchHandle(theDialog, ok), kControlButtonPart);
  558.                                 Delay(8, &tempLong);        /* wait about 8 ticks so they can see it */
  559.                                 HiliteControl(SnatchHandle(theDialog, ok), false);
  560.                                 
  561.                                 retVal = true;
  562.                             }
  563.                             break;
  564.                             
  565.                         default:
  566.                             /* nothing */
  567.                             break;
  568.                     }
  569.                 }
  570.             }
  571.         }
  572.     }
  573.     
  574.     /* did anything actually happen? */
  575.     if (upOrDown)
  576.         AdjustDate(upOrDown - 1, theDialog, -1);
  577.     
  578.     SetPort(theOld);
  579.     return(retVal);
  580. }
  581.  
  582. /* end DateThingerFilter */
  583.  
  584. /* DateSetterDialog */
  585. /* actually displays and runs the dialog */
  586. void DateSetterDialog(void)
  587. {
  588.     DialogPtr tdial = GetNewDialog(kDateDialog, nil, (WindowPtr)-1);
  589.     short hitItem;
  590.     Boolean noExit = true;
  591.     short kindI;
  592.     Handle HandL;
  593.     Rect itemRect;
  594.     
  595.     /* set up our date thing user item */
  596.     GetDialogItem(tdial, kManDateItem, &kindI, &HandL, &itemRect);
  597.     SetDialogItem(tdial, kManDateItem, userItem, (Handle)NewControlUserPaneDrawProc(DateBox), &itemRect);
  598.     
  599.     /* default some values */
  600.     dialogDateStruct.editHot = true;
  601.     dialogDateStruct.whichHitting = 0;
  602.     GetDateTime(&dialogDateStruct.dialogDate.startDateraw);
  603.     GetDateTime(&dialogDateStruct.dialogDate.endDateraw);
  604.     SecondsToDate(dialogDateStruct.dialogDate.startDateraw, &dialogDateStruct.dialogDate.startDate);
  605.     SecondsToDate(dialogDateStruct.dialogDate.endDateraw, &dialogDateStruct.dialogDate.endDate);
  606.     
  607.     /* set up for bordering OK */
  608.     GetDialogItem(tdial, kBorderBox, &kindI, &HandL, &itemRect);
  609.     SetDialogItem(tdial, kBorderBox, kindI, (Handle)NewControlUserPaneDrawProc(BorderDefault), &itemRect);
  610.     
  611.     /* dialog was created hidden, so show it */
  612.     ShowWindow(tdial);
  613.     DrawDialog(tdial);
  614.     
  615.     do {
  616.         ModalDialog(NewModalFilterProc(DateThingerFilter), &hitItem);
  617.         switch (hitItem) {
  618.             case ok:
  619.             case cancel:
  620.                 noExit = false;
  621.                 break;
  622.         }
  623.     }
  624.             while (noExit);
  625.     if (hitItem == ok) {
  626.         
  627.     }
  628.     DisposeDialog(tdial);
  629.     
  630. }
  631.  
  632. /* end DateSetterDialog */
  633.